package app.common.utils.wdt.sdk.taobao;

import com.alibaba.fastjson.JSON;
import com.taobao.api.BaseTaobaoRequest;
import com.taobao.api.TaobaoResponse;
import org.apache.commons.codec.digest.DigestUtils;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

public class Utils
{
	private Utils()
	{
	}

	private static final List<String> QIMEN_CRM_SIGNED_FIELDS = Arrays
			.asList("pageNo", "pageSize", "fields", "extendProps", "customerid", "method", "sd_code", "startModified",
					"endModified");
	private static final List<String> QIMEN_EXCLUDE_SIGN_FIELDS = Arrays.asList("wdt3_customer_id", "wdt_sign");

	/**
	 * 获取奇门自定义接口的签名
	 *
	 * @param request   请求
	 * @param wdtSecret app_secret的前半部分
	 * @return 签名值
	 */
	public static <T extends TaobaoResponse> String getQimenCustomWdtSign(BaseTaobaoRequest<T> request, String wdtSecret)
	{
		Map<String, String> params = request.getTextParams();
		params.put("method", request.getApiMethodName());

		System.out.println("params:" + params);

		StringBuilder toBeSignedStringBuilder = new StringBuilder();
		getToBeSignedString(toBeSignedStringBuilder, params);
		toBeSignedStringBuilder.insert(0, wdtSecret).append(wdtSecret);

		System.out.println("toBeSignedString: " + toBeSignedStringBuilder);

		System.out.println("result:" + DigestUtils.md5Hex(toBeSignedStringBuilder.toString()));

		return DigestUtils.md5Hex(toBeSignedStringBuilder.toString());
	}

//	private static boolean isValidJson(String content)
	public static boolean isValidJson(String content)
	{
		if (null == content)
			return false;

		String trimmedContent = content.trim();
		if (!(trimmedContent.startsWith("{") && trimmedContent.endsWith("}")) && !(trimmedContent.startsWith("[") && trimmedContent.endsWith("]")))
			return false ;

		return JSON.isValid(content);
	}

	@SuppressWarnings("unchecked")
	private static void getToBeSignedString(StringBuilder stringBuilder, Object object)
	{
		if (object instanceof Map)
		{
			@SuppressWarnings("unchecked")
			Map<String, Object> map = (Map<String, Object>) object;
			map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEachOrdered(p -> {
				if (QIMEN_EXCLUDE_SIGN_FIELDS.contains(p.getKey()) || null == p.getValue())
					return;

				stringBuilder.append(p.getKey());

				Object value = p.getValue();

				if (value instanceof Integer)
				{
					stringBuilder.append(value);
				}
				else if (value instanceof String)
				{
					if (JSON.isValidObject(value.toString()))
					{
						getToBeSignedString(stringBuilder, JSON.parseObject(p.getValue().toString(), Map.class));
					}
					else if (JSON.isValidArray(value.toString()))
					{
						for (Object obj : JSON.parseArray(value.toString(), Object.class))
						{
							getToBeSignedString(stringBuilder, obj);
						}
					}
					else
					{
						stringBuilder.append((String) value);
					}
				}
				else if (value instanceof BigDecimal)
				{
					stringBuilder.append(((BigDecimal) value).toPlainString());
				}
				else if (value instanceof Long)
				{
					stringBuilder.append(value);
				}
				else if (value instanceof Boolean)
				{
					stringBuilder.append(((Boolean) value).booleanValue());
				}
				else if (value instanceof Float)
				{
					stringBuilder.append(value);
				}
				else if (value instanceof Double)
				{
					stringBuilder.append(value);
				}
				else
				{
					getToBeSignedString(stringBuilder, value);
				}

			});
		}
		else if (object instanceof List)
		{
			for (Map map : (List<Map>) object)
			{
				getToBeSignedString(stringBuilder, map);
			}
		}
		else
		{
			stringBuilder.append(object.toString());
		}
	}

	static <T extends TaobaoResponse> String getQimenOfficialWdtSign(BaseTaobaoRequest<T> request, String secret)
	{
		Map<String, String> params = request.getTextParams();
		params.put("method", request.getApiMethodName());
		params.entrySet().removeIf(e -> !QIMEN_CRM_SIGNED_FIELDS.contains(e.getKey()));
		StringBuilder toBeSignedStringBuilder = new StringBuilder();
		getToBeSignedString(toBeSignedStringBuilder, params);
		toBeSignedStringBuilder.insert(0, secret).append(secret);

		return DigestUtils.md5Hex(toBeSignedStringBuilder.toString());
	}
}
